use super::spinlock::{SpinLock, SpinLockGuard};
use crate::mem_io;
use core::fmt;
pub const VGA_WIDTH: usize = 80;
pub const VGA_HEIGHT: usize = 25;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
    Black = 0,
    Blue,
    Green,
    Cyan,
    Red,
    Magenta,
    Brown,
    LightGray,
    DarkGray,
    LightBlue,
    LightGreen,
    LightCyan,
    LightRed,
    Pink,
    Yellow,
    White,
}


#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
struct ColorCode(u8);

impl ColorCode {
    fn new(foreground: Color, background: Color) -> ColorCode {
        ColorCode((background as u8) << 4 | (foreground as u8))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
struct ScreenChar {
    ascii_character: u8,
    color_code: u8,
}
impl ScreenChar {
    fn new(ch: u8, color: ColorCode) -> Self {
        ScreenChar {
            ascii_character: ch,
            color_code: color.0,
        }
    }
    fn as_u16(&self) -> u16 {
        (self.color_code as u16) << 8 | (self.ascii_character as u16)
    }
}

struct VgaBuffer {
    base_address: usize,
}
impl VgaBuffer {
    // 写入字符到指定位置
    fn write_char(&mut self, row: usize, col: usize, char: ScreenChar) {
        let offset = row * VGA_WIDTH + col;
        let address = (self.base_address + offset * 2) as *mut u16;
        mem_io::write_vga_char(address, char.as_u16());
    }
    // 读取指定位置的字符
    fn read_char(&self, row: usize, col: usize) -> ScreenChar {
        let offset = row * VGA_WIDTH + col;
        let address = (self.base_address + offset * 2) as *const u16;
        let value = mem_io::read_vga_char(address) ;
        
        ScreenChar {
            ascii_character: (value & 0xFF) as u8,
            color_code: ((value >> 8) & 0xFF) as u8,
        }
    }
}


pub struct Writer {
    column_position: usize,
    color_code: ColorCode,
    buffer: VgaBuffer,
}
pub static WRITER: SpinLock<Option<Writer>> = SpinLock::new(None);
fn get_writer() -> SpinLockGuard<'static, Option<Writer>> {
    WRITER.lock()
}

impl Writer {
    pub fn write_byte(&mut self, byte: u8) {
        match byte {
            b'\n' => self.new_line(),
            byte => {
                if self.column_position >= VGA_WIDTH {
                    self.new_line();
                }

                let row = VGA_HEIGHT - 1;
                let col = self.column_position;
                
                // 创建屏幕字符并写入
                let screen_char = ScreenChar::new(byte, self.color_code);
                self.buffer.write_char(row, col, screen_char);
                
                self.column_position += 1;
            }
        }
    }

    fn new_line(&mut self) {
        // 将每一行向上移动一行
        for row in 1..VGA_HEIGHT {
            for col in 0..VGA_WIDTH {
                // 读取当前行的字符
                let ch = self.buffer.read_char(row, col);
                // 写入上一行
                self.buffer.write_char(row - 1, col, ch);
            }
        }
        
        // 清除最后一行
        self.clear_row(VGA_HEIGHT - 1);
        self.column_position = 0;
    }

    fn clear_row(&mut self, row: usize) {
        let blank = ScreenChar::new(b' ', self.color_code);
        for col in 0..VGA_WIDTH {
            self.buffer.write_char(row, col, blank);
        }
    }
}

impl fmt::Write for Writer {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for byte in s.bytes() {
            match byte {
                // 可打印字符或换行符
                0x20..=0x7e | b'\n' => self.write_byte(byte),
                // 不可打印字符
                _ => self.write_byte(0xfe),
            }
        }
        Ok(())
    }
}


#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ($crate::vga::_print(format_args!($($arg)*)));
}

#[macro_export]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}

#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
    use core::fmt::Write;
    // WRITER.lock().as_mut().unwrap().write_fmt(args).unwrap();
    // 获取锁
    let mut guard = get_writer();

    // 检查是否已初始化
    if let Some(writer) = guard.as_mut() {
        // 写入格式化文本
        writer.write_fmt(args).unwrap();
    } else {
        // 如果未初始化，尝试初始化
        drop(guard); // 先释放锁
        init();

        // 再次尝试打印
        let mut guard = get_writer();
        if let Some(writer) = guard.as_mut() {
            writer.write_fmt(args).unwrap();
        }
    }
}

pub fn init() {
    // 创建VGA缓冲区实例
    let mut buffer = VgaBuffer {
        base_address: 0xb8000,
    };
    
    // 清屏：用空格覆盖整个屏幕
    let clear_char = ScreenChar::new(b' ', ColorCode::new(Color::White, Color::Black));
    for row in 0..VGA_HEIGHT {
        for col in 0..VGA_WIDTH {
            buffer.write_char(row, col, clear_char);
        }
    }

    // 初始化WRITER
    let mut writer = WRITER.lock();
    *writer = Some(Writer {
        column_position: 0,
        color_code: ColorCode::new(Color::Yellow, Color::Black),
        buffer,
    });
}
